/*
 * JsonRpcInterface.cpp
 *
 *  Created on: Mar 16, 2017
 *      Author: zhangjf
 */

#include <map>
#include <string>
#include <Poco/Logger.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Util/Application.h>
#include <Poco/Dynamic/Var.h>

#include "WCIAppServConnector.h"
#include "WebCallInterface.h"
#include "WCILogin.h"
#include "WCILogout.h"
#include "WCIGetAppList.h"
#include "WCIGetCellTypeList.h"
#include "WCIGetAppProperties.h"

using namespace Poco;
using namespace Poco::JSON;
using namespace Poco::Dynamic;
using namespace Poco::Util;

const std::string WebCallInterface::_strMethod = "method";
const std::string WebCallInterface::_strJsonRpc = "jsonrpc";
const std::string WebCallInterface::_strParams = "params";
const std::string WebCallInterface::_strID = "id";

std::map<std::string, std::function<WebCallInterface::Ptr(Object::Ptr&)>> WebCallInterfaceFactory::mapJRI;

WebCallInterface::WebCallInterface(const std::string& name, Object::Ptr& joParams)
: _joParams(joParams)
, _joResult()
, _joError()
, _strMethodName(name)
{
	// TODO Auto-generated constructor stub

}

bool WebCallInterface::process()
{
	bool blRet = false;

	poco_information(Application::instance().logger(), "run " + _strMethodName + "::process()");

	Object joReq;
	joReq.set(_strJsonRpc, "2.0");
	joReq.set(_strMethod, _strMethodName);
	joReq.set(_strParams, _joParams);
	joReq.set(_strID, getSeqID());

	std::string strReq = ((DynamicStruct)joReq).toString();
	std::string strResp;

	try
	{
		if (!preprocess(strReq))
		{
			poco_information(Application::instance().logger(), "error: " + _strMethodName + "::preprocess() failed");
			throw Exception(_strMethodName + "::preprocess() failed");
		}
		if ((blRet = WCIAppServConnector::request(strReq, strResp)) == true)
		{
			if (!postprocess(strResp))
			{
				poco_information(Application::instance().logger(), "error: " + _strMethodName + "::postprocess() failed");
				throw Exception(_strMethodName + "::postprocess() failed");
			}

			Parser parser;
			Object::Ptr joResp = parser.parse(strResp).extract<Object::Ptr>();
			if (joResp->has("result"))
			{
				_joResult = *joResp->getObject("result");
				blRet = true;
			}
			else if (joResp->has("error"))
			{
				_joError = *joResp->getObject("error");
				blRet = true;
			}
			else
			{
				poco_information(Application::instance().logger(), "error: " + _strMethodName + "::not found result && error in response");
				_joError.set("code", -32004);
				_joError.set("message", "Server internal error");
			}
		}
		else
		{
			poco_information(Application::instance().logger(), "error: " + _strMethodName + "::request() failed");
			_joError.set("code", -32004);
			_joError.set("message", "Server internal error");
		}
	}
	catch (Exception& exc)
	{
		poco_information(Application::instance().logger(), "error: " + _strMethodName + "::" + exc.message());
		_joError.set("code", -32004);
		_joError.set("message", "Server internal error : " + exc.message());
	}

	return blRet;
}

WebCallInterface::~WebCallInterface()
{
	// TODO Auto-generated destructor stub
}

WebCallInterface::Ptr WebCallInterfaceFactory::createInterface(std::string& interface, Object::Ptr& joParams)
{
	if (mapJRI.size() == 0)
	{
		initialize();
	}

	return mapJRI[interface](joParams);
}

void WebCallInterfaceFactory::initialize()
{
	mapJRI["Login"] = [](Object::Ptr& joParams){ return WebCallInterface::Ptr(new WCILogin(joParams)); };
	mapJRI["Logout"] = [](Object::Ptr& joParams){ return WebCallInterface::Ptr(new WCILogout(joParams)); };
	mapJRI["GetCellTypeList"] = [](Object::Ptr& joParams){ return WebCallInterface::Ptr(new WCIGetCellTypeList(joParams)); };
	mapJRI["GetAppList"] = [](Object::Ptr& joParams){ return WebCallInterface::Ptr(new WCIGetAppList(joParams)); };
	mapJRI["GetAppProperties"] = [](Object::Ptr& joParams){ return WebCallInterface::Ptr(new WCIGetAppProperties(joParams)); };
}

